<template>
  <div class="page">
    <div class="answer">
      <div class="answerLeft">
        <div style="padding-bottom: 15px; border-bottom: 1px solid #dcdfe6;">
          <button class="createChat-button" @click="onClickCreateChat" plain type="primary">新建会话</button>
        </div>
        <div @click="onClickChatItem(item)" v-for="item in chatHistory.list" :key="item.id">
          <template v-if="!item._edit">
            <div :class="['chatHistory-item', { 'is-active': item.id === chatHistory.questionId }]">
              <div class="chatHistory-item__bd">{{ item.title }}</div>
              <div class="chatHistory-item__handle" @click.stop>
                <uni-icons @click="onClickEditTitle(item)" type="compose" class="modify-icon"></uni-icons>
                <!-- <el-popover 
                  :ref="`popover-${item.id}`"
                  placement="top"
                  width="220" trigger="click">
                  <p class="answerLeft-deleteConfirm">删除后无法恢复，是否继续删除？</p>
                  <div style="text-align: center; margin: 0">
                    <button class="answerLeft-deleteConfirm__btn" @click="$refs[`popover-${item.id}`][0].doClose()">取消</button>
                    <button @click="confirmDeletion(item)" class="answerLeft-deleteConfirm__btn" type="primary">确定</button>
                  </div>
                  <i @click.stop slot="reference" class="el-icon-delete modify-icon"></i>
                </el-popover> -->
                <uni-icons @click="confirmDeletion(item)" type="trash" class="modify-icon"></uni-icons>
              </div>
            </div>
          </template>
          <template v-else>
            <div @click.stop :class="['chatHistory-item', { 'is-active': item.id === chatHistory.questionId }]">
              <div class="chatHistory-item__bd">
                <input class="modify-title" maxlength="20" />
              </div>
              <div class="chatHistory-item__handle">
                <uni-icons @click="saveChatTitle(item)" type="checkmarkempty" class="modify-icon"></uni-icons>
                <uni-icons @click="item._edit = false" type="closeempty" class="modify-icon"></uni-icons>
              </div>
            </div>
          </template>
        </div>
      </div>
      <div class="answerMain">
        <div class="answerMain-bd">
          <div class="answerMain-item">
            <img src="@/static/ai-avatar.png" class="answerMain-item__avatar" />
            <div class="answerMain-item__content" style="padding: 20px 28px;">
              <span class="defaultQuestion-title">您好，我是智能助手！</span>
              作为您的智能助手，我能帮助您解决各种问题。
              除此之外，小助还可以尝试帮助解决其他方面的问题或在您需要的时候陪您聊天！
              您可以试着问我：
              <div class="defaultQuestion">
                <div  class="defaultQuestion-item" @click="onClickDefaultQuestion($event, item)" v-for="item in defaultQuestion.list" :key="item.id" :span="12">
                  {{ item.value }}
                </div>
              </div>
            </div>
          </div>
          <div v-for="item in answerList" :class="['answerMain-item', {'roleUser': item.role === 'user' }]">
            <img v-show="item.role === 'assistant'" src="@/static/ai-avatar.png" class="answerMain-item__avatar" />
            <img v-show="item.role === 'user'" src="@/static/ai-question-avatar.png" class="answerMain-item__avatar" />
            <div class="">
              
              <div v-if="item.role === 'user'" class="answerMain-item__content">{{ item.content }}</div>
              <div v-else-if="item.role === 'assistant'" class="answerMain-item__content">
                <div class="answerMain-item__outputReasonContent">{{ item.reasoning_content }}</div>
                <zero-markdown-view :markdown="item.content" themeColor="#05073b"></zero-markdown-view>
              </div>
            </div>
          </div>
        </div>
        <div class="answerMain-ft">
          <div class="answerMain-input">
            <textarea v-model.trim="answerKeyword" @keydown.enter.native="onSubmit" placeholder="请输入问题，可通过shift+回车换行" class="answerMain-input__textarea"></textarea>
            <div style="display: flex; justify-content: flex-end;">
              <button @click="onSubmit" :loading="submitLoading" type="primary" class="answerMain-input__button">
                发送
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  components: {},
  data() {
    return {
			buffer: '', // 用于存储流式数据不完整的行
      defaultQuestion: {
        list: [
          { id: 2, value: '如何看待中国锂矿储量从全球占比6%升至16.5%，从世界第六跃至第二？', },
          { id: 3, value: '为什么特斯拉和理想，都不想承认自己是「汽车公司」？', },
          { id: 4, value: '全美第二大的城市洛杉矶大火，为什么能蔓延到无法控制的地步？', },
          { id: 4, value: '为什么主流都不再力推英特尔 CPU？', },
        ]
      },
      submitLoading: false,
      answerKeyword: undefined,
      answerList: [],
      // 会话记录
      chatHistory: {
        list: [],
        questionId: undefined,
      }
    }
  },
  created() {
    this.getChatList()
  },

  methods: {
    onClickCreateChat() {
      if (this.chatHistory.list.length >= 10) {
        return uni.showToast({ title: '您最多可同时建立10个对话，如需新建对话，请先删除会话！', icon: 'none' })
      }
      this.chatHistory.questionId = undefined
      this.answerList = []
      this.answerKeyword = undefined
    },
    onClickEditTitle(item) {
      this.chatHistory.list.map(item => item._edit = false)
      item._edit = true
      this.$nextTick(() => {
  
      })
    },

    saveChatTitle(item) {
      uni.showToast({ title: '触发修改', icon: 'none' })
      this.getChatList()
    },
    confirmDeletion(item) {
      uni.showModal({ title: '提示', content: '确定删除吗' })
    },
    onClickDefaultQuestion(event, item) {
      this.answerKeyword = item.value
      this.onSubmit(event)
    },

    getChatList() {
      setTimeout(() => {
        this.chatHistory.list = [
          {
            "id": 31,
            "title": "统计学专业就业好不好？",
            "createDate": "2024-07-31 15:13:49",
            "updateDate": null,
            "itemList": [
              {
                "id": 136,
                "questionId": 30,
                "role": "user",
                "content": "统计学专业就业好不好？",
                "createDate": "2024-07-31 15:13:49",
                "updateDate": null
              },
              {
                "id": 137,
                "questionId": 30,
                "role": "assistant",
                "content": "#### 统计学专业的就业前景相对较好，具有广阔的发展空间。",
                "reasoning_content": "统计学专业的就业前景相对较好，具有广阔的发展空间。",
                "createDate": "2024-07-31 15:13:49",
                "updateDate": null
              }
            ]
          }
        ]
      }, 1000);
      this.chatHistory.list.map(item => {
        item._edit = false
        item._editTitle = item.title
        return item
      })
    },

    onClickChatItem(item) {
      this.chatHistory.questionId = item.id
      this.answerList = item.itemList

      this.$nextTick(() => {
        let elem = document.querySelector('.answerMain-bd')
        elem.scrollTop = elem.scrollHeight
      })
    },


    async onSubmit(event) {
      console.log('event', event);
      if (event.keyCode === 13 || event.key === "Enter") {
        event.preventDefault(); // 阻止默认行为，即回车换行
        if (event.shiftKey) {
          this.answerKeyword += "\n";
        }
      }
      if (!this.answerKeyword) {
        return uni.showToast({ title: '请输入内容', icon: 'none' })
      }
      if (this.submitLoading) return
      this.submitLoading = true
      this.answerList.push({
        role: 'user',
        content: this.answerKeyword,
      })
      this.answerKeyword = undefined
	  
	  // this.answerList.push({
	  //   role: 'assistant',
	  //   content: '我也不知道说什么了',
	  //   reasoning_content: '',
	  // })
	  // done = true;
	  
      let response = await fetch(`http://127.0.0.1:11551/api/health`, {
        method: "GET",
        headers: {
          satoken: sessionStorage.getItem("satoken"),
          userId: sessionStorage.getItem("userId"),
          'Content-Type': 'application/json; charset=utf-8',
          'Access-Control-Allow-Origin': '*'
        },
        body: JSON.stringify({
          questionId: this.chatHistory.questionId,
          list: this.answerList.slice(-30),
        }),
      });
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      const reader = response.body.getReader();
      // 定义一个函数来读取流数据
      this.answerList.push({
        role: 'assistant',
        content: '',
        reasoning_content: '',
      })
      const that = this
      function readStream() {
        reader.read().then(({ done, value }) => {
          // 如果流已经读取完毕
          if (done) {
            console.log('Stream complete');
            that.submitLoading = false
            console.log('that', that.answerList);
            return;
          }
          // 处理当前读取到的数据块
          let itemText = new TextDecoder().decode(value, { stream: true })
          that.processSSEChunk(itemText)
          // 继续读取下一个数据块
          readStream();
        }).catch(error => {
          console.error('Error reading stream:', error);
        });
      }

      // 开始读取流
      readStream();
    },
		processSSEChunk(chunk) {
			// 按行拆分数据块
			this.buffer += chunk
			const lines = this.buffer.split('data:')
			// 检查最后一行是否完整
			if (!chunk.endsWith('\n')) {
				// 如果最后一行不完整，保留在缓冲区中
				this.buffer = lines.pop();
			} else {
				// 如果最后一行完整，清空缓冲区
				this.buffer = '';
			}
			lines.forEach((line, index) => {
				// 检查是否是SSE格式的数据行
					// 提取JSON部分
				const jsonString = line;
				// 如果JSON部分不为空，则解析
				if (jsonString === '[DONE]') {
					this.answerList[this.answerList.length - 1].content += ''
				} else if (jsonString !== '') {
					try {
						const jsonData = JSON.parse(jsonString);
						if (jsonData.questionId && !this.chatHistory.questionId) {
							this.getChatList()
							this.chatHistory.questionId = jsonData.questionId
						}
						if (jsonData.reasoning_content) {
							this.answerList[this.answerList.length - 1].reasoning_content += jsonData.reasoning_content
						} else if (jsonData.content) {
							this.answerList[this.answerList.length - 1].content += jsonData.content
						}
					} catch (error) {
						console.log('parsing JSON错误', jsonString, index);
						console.log('parsing JSON错误', error);
					}
				}
				this.$nextTick(() => {
					let elem = document.querySelector('.answerMain-bd')
					elem.scrollTop = elem.scrollHeight
					// window.scrollTo(0, document.body.scrollHeight)
				})
			});
		},
  },
}
</script>

<style lang="scss" scoped>
uni-page-body, html, body {
  height: 100%;
}
.page {
	background: #f9f9f9;
  height: 100%;
}
.modify-icon {
	display: inline-block;
	font-size: 14px;
	padding: 5px;
	cursor: pointer;
	&:hover {
		background: #e1e5fa;
		border-radius: 4px;
		color: PrimaryColor;
	}
}
.createChat-button {
  font-size: 14px;
}

.defaultQuestion-title {
	color: #05073b;
	font-size: 26px;
	font-weight: 600;
	line-height: 36px;
	margin-bottom: 8px;
}
.defaultQuestion {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  column-gap: 10px;
}
.defaultQuestion-item {
	padding: 16px;
	background: #f6f8fd;
	border-radius: 6px;
	margin-top: 10px;
	cursor: pointer;
	font-size: 16px;
	font-weight: 600;
	.modify-icon {
		font-size: 16px;
		&:hover {
			background: unset;
		}
	}
	&:hover {
		background: #e9ecfb;
		color: PrimaryColor;
	}
}
.answer {
	display: flex;
	justify-content: center;
	height: 100%;
	padding: 10px;
	box-sizing: border-box;
}
.answerLeft {
	width: 280px;
	margin-right: 10px;
	background: linear-gradient(180deg, #f5f4f6, #e6ebf7);
	border-radius: 8px;
	padding: 15px 10px 0 10px;
}
.answerLeft-deleteConfirm {
	padding: 12px 0;
	text-align: center;
}
.answerLeft-deleteConfirm__btn {
	width: 92px;
	height: 32px;
	line-height: 32px;
	padding: 0 4px;
}

.modify-title {
  border: 1px solid #dcdfe6;
  height: 32px;
  line-height: 32px;
  border-radius: 8px;
  width: 100%;
  padding: 0 12px;
}
.answerMain {
	padding-top: 9px;
	font-size: 15px;
	display: flex;
	flex-direction: column;
	background: linear-gradient(180deg, #f5f4f6, #e6ebf7);
	width: 900px;
	border-radius: 8px;
}
.answerMain-bd {
	flex-grow: 1;
	height: 0;
	overflow-y: auto;
	flex-direction: column;
	display: flex;
	background: unset;
	box-sizing: border-box;
	&::-webkit-scrollbar-thumb {
		border-radius: 4px;
		background: rgba(108,119,143,0.3);
	}
	&::-webkit-scrollbar {
		height: 20px;
		width: 4px;
	}
}
.answerMain-ft {
	flex-shrink: 0;
	min-height: 50px;
	padding: 12px 82px 30px 82px;
	box-sizing: border-box;
}
.chatHistory-item {
	display: flex;
	align-items: center;
	padding: 0 10px 0 0;
	margin-top: 10px;
	&:hover {
		.chatHistory-item__handle {
			display: block;
		}
	}
}
.chatHistory-item:hover,
.chatHistory-item.is-active {
	background: rgba(255,255,255,0.9);
	border-radius: 8px;
	box-shadow: 0 16px 20px 0 rgba(173,167,224,0.06);
	color: initial;
}
.chatHistory-item__hd {
	flex-shrink: 0;
}
.chatHistory-item__bd {
	flex: 1;
	color: #000c3f;
	cursor: pointer;
  display: flex;
  align-items: center;
	font-size: 14px;
	font-weight: 400;
	height: 50px;
	line-height: 50px;
	overflow: hidden;
	padding: 0 10px 0 10px;
	position: relative;
	text-align: justify;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.chatHistory-item__handle {
	flex-shrink: 0;
	display: none;
}
.answerMain-item {
	padding: 6px 82px;
	color: #05073b;
	position: relative;
	display: flex;
	&.roleUser {
		justify-content: end;
		.answerMain-item__avatar {
			left: unset;
			right: 40px;
		}
	}
}
.answerMain-item__avatar {
	width: 26px;
	height: 26px;
	border-radius: 50%;
	position: absolute;
	top: 12px;
	left: 40px;
}
.answerMain-item__content {
	background: #fdfdfe;
	border-radius: 8px;
	box-shadow: 0 16px 20px 0 rgba(174,167,223,0.06);
	display: flex;
	flex-direction: column;
	padding: 12px 20px;
	position: relative;
	font-size: 15px;
	line-height: 1.75;
  min-height: 50px;
  box-sizing: border-box;
}
.answerMain-item__outputReasonContent {
  color: #666;
  border-left: 3px solid #ddd;
  padding-left: 13px;
  margin: 5px 0;
  line-height: 1.5;
}
.answerMain-input {
	background: #fff;
	padding: 12px 16px;
	border-radius: 10px;
	box-shadow: 0 16px 20px 0 rgba(174,167,223,0.2);
	min-height: 50px;
}
.answerMain-input__textarea {
	height: 50px;
  width: 100%;
	::v-deep {
		.el-textarea__inner {
			border: none;
			resize: none;
			color: #05073b;
		}
	}
}
.answerMain-input__button {
	font-size: 12px;
	padding: 0 20px;
	align-self: end;
  margin: 0;
}

</style>
